package com.joe.test_mybatis_plus.exception;

import com.fasterxml.jackson.core.JsonParseException;
import com.joe.test_mybatis_plus.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;


/**
 * @Description   全局异常
 * @Author        Joe
 * @Company       Jycx
 * @CreateDate    2021/9/8 11:43
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 数据结构不匹配
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = JsonParseException.class)
    public Result jsonParseExceptionHandler(JsonParseException e) {
        log.error("GlobalExceptionHandler| jsonParseExceptionHandler| json解析异常", e);
        return Result.fail("json数据解析异常，请检查数据结构");
    }

    /**
     * 字段类型不匹配
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public Result messageExceptionHandler(HttpMessageNotReadableException e) {
        log.error("http请求参数转换异常: {}", e.getMessage());
        return Result.fail("参数转换异常，请检查字段类型");
    }

    /**
     * 空指针异常
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({NullPointerException.class})
    public Result nullPointerException(NullPointerException e) {
        log.error("发生空指针异常！原因是:",e);
        return Result.fail("发生空指针异常，请联系开发人员");
    }

    /**
     * 必传参数不得为空
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public Result missingServletRequestParameterException(MissingServletRequestParameterException e){
        log.error("必传参数不得为空！原因是:",e);
        return Result.fail("必传参数不得为空");
    }

    /**
     * SQL执行异常
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = DataAccessException.class)
    public Result sqlException(DataAccessException e){
        log.error("SQL执行异常！原因是:",e.getMessage());
        return Result.fail("SQL执行异常，请联系开发人员");
    }

    /**
     * 索引越界异常
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = IndexOutOfBoundsException.class)
    public Result indexOutOfBoundsException(IndexOutOfBoundsException e){
        log.error("索引越界异常！原因是:",e);
        return Result.fail("索引越界异常，请联系开发人员");
    }
    /**
     * 全局大范围补充
     * @param e
     * @return
     */
//    @ResponseStatus(HttpStatus.BAD_REQUEST)
//    @ExceptionHandler(value = RuntimeException.class)
//    public Result handler(RuntimeException e){
//        log.error("运行时异常----------------------:{}",e.getMessage());
//        return Result.fail(e.getMessage());
//    }


    /**
     * shiro的异常
     * @param e
     * @return
     */
    /*@ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(value = ShiroException.class)
    public Result handler(ShiroException e){
        log.error("权限异常：----------------------",e);
        return Result.fail(401,e.getMessage(),null);
    }*/

    /**
     * 实体类校验异常
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handler(MethodArgumentNotValidException e){
        log.error("实体校验异常：----------------------:{}",e);
        BindingResult bindResult = e.getBindingResult();
        ObjectError objectError = bindResult.getAllErrors().stream().findFirst().get();
        String defaultMessage = objectError.getDefaultMessage();

        return Result.fail(defaultMessage);
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = IllegalArgumentException.class)
    public Result handler(IllegalArgumentException e){
        log.error("Assert异常：----------------------:{}",e);
        return Result.fail(e.getMessage());
    }
}
